package org.xdj.blue.java.nio.client;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 客户端线程
 * 
 * @author 91power—xdj
 * 
 */
public class NioSocketClient implements Runnable {
	private String ip;
	private int port;
	private Selector selector;
	private SocketChannel socketChannel;
	private volatile boolean stop;

	public static Logger logger = LoggerFactory
			.getLogger(NioSocketClient.class);

	/**
	 * 构造方法
	 * 
	 * @param ip
	 * @param port
	 */
	public NioSocketClient(String ip, int port) {
		this.ip = ip;
		this.port = port;
		try {
			selector = Selector.open();
			socketChannel = SocketChannel.open();
			socketChannel.configureBlocking(false);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 执行
	 */
	public void run() {
		try {
			doConnect();
			while (!stop) {
				selector.select(1000);
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> it = keys.iterator();
				SelectionKey key = null;
				while (it.hasNext()) {
					key = it.next();
					it.remove();
					handle(key);
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		if (selector != null) {
			try {
				selector.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 连接
	 * 
	 * @throws IOException
	 */
	private void doConnect() throws IOException {
		if (socketChannel.connect(new InetSocketAddress(ip, port))) {
			logger.debug("--doConnect--");
			socketChannel.register(selector, SelectionKey.OP_READ);
			String request = "client request connect to server--" + new Date();
			doWrite(socketChannel, request);
		} else {
			socketChannel.register(selector, SelectionKey.OP_CONNECT);
		}
	}

	/**
	 * 处理
	 * 
	 * @param key
	 * @throws IOException
	 */
	private void handle(SelectionKey key) throws IOException {
		if (key.isValid()) {
			SocketChannel sc = (SocketChannel) key.channel();
			if (key.isConnectable()) {
				if (sc.finishConnect()) {
					logger.debug("--finishConnect--");
					sc.register(selector, SelectionKey.OP_READ);
					String request = "client want connect to server--"
							+ new Date();
					doWrite(sc, request);
				}
			}
			if (key.isReadable()) {
				ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
				int readBytes = sc.read(byteBuffer);
				if (readBytes > 0) {
					byteBuffer.flip();
					byte[] bytes = new byte[byteBuffer.remaining()];
					byteBuffer.get(bytes);
					String body = new String(bytes, "UTF-8");
					logger.debug("--客户端接受到信息：" + body);
					this.stop = true;
				}
			}
		}
	}

	/**
	 * 写入
	 * 
	 * @param sc
	 * @param request
	 * @throws IOException
	 */
	private void doWrite(SocketChannel sc, String request) throws IOException {
		logger.debug("--doWrite--");

		if (request != null && request.trim().length() > 0) {
			byte[] bytes = request.getBytes();
			ByteBuffer writeBuff = ByteBuffer.allocate(bytes.length);
			writeBuff.put(bytes);
			writeBuff.flip();
			sc.write(writeBuff);
			if (!writeBuff.hasRemaining()) {
				logger.debug("--request sucess--");
			}
		}
	}
}
